home *** CD-ROM | disk | FTP | other *** search
- /*==================================================================
- * File : main.c
- * Package: Xprof
- *
- * Author : Aloke Gupta.
- *
- * (C) Copyright 1992, Aloke Gupta.
- *==================================================================*/
-
- /*
- * main.c: Main function definitions
- * Functions:
- * 1. main(int argc, char **argv)
- * 2. process_client(char *string, GlobalStats gstats)
- * 3. process_server(char *string, GlobalStats gstats)
- * 4. print_stats(FILE *fp)
- * 5. process_stats(FILE *fp,long min, long max, long *distbn, Grain grain,
- * long maxbuckets, StatsType statstype)
- * 6. Signal handlers defined by ONSIGNAL(function, string, terminate)
- * 7. t_search(char *string, char *token)
- */
-
- static char copyright[] =
- "@(#) Copyright (c) 1992 Aloke Gupta.\n\
- All rights reserved.\n";
-
- #define VERSION "1.01"
- static char *xprof_version = VERSION;
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <signal.h>
- #include<sys/time.h>
- #include "common.h"
-
- void set_net_latency( /* double */);
- void set_net_speed ( /* double */);
-
- #define FILENAMESIZE 128
-
- /*
- * The following are signal handlers defined at the end of this file
- */
- void onhangup();
- void onintr();
- void onquit();
- void onfpe();
- void onbus();
- void onsegv();
- void onxcpu();
-
- int debuglevel = 0;
- int verboselevel = 2;
- int trapsignal = TRUE; /* Trap signals ? */
- Boolean profileflag = FALSE; /* This flag should be set only if a parameters
- file is specified on the command line */
- long _LINE_NUM = 0; /* The current line number */
-
- GlobalStats globalstats;
-
- Usage(prog_name, badfield)
- char *prog_name;
- char *badfield;
- {
- if (badfield != NULL)
- fprintf(stderr,"\n\t** Unknown option: \"%s\" **\n",badfield);
- fprintf(stderr, " Usage: %-8s ", prog_name);
- fprintf(stderr, "-d<debuglevel> ");
- fprintf(stderr, "-v<verboselevel> ");
- fprintf(stderr, "-p<perffile>");
- fprintf(stderr, "\n ");
- fprintf(stderr, "-b<num_buckets> ");
- fprintf(stderr, "-s<trapsignal> ");
- fprintf(stderr, "\n ");
- fprintf(stderr, "-S<Net Speed (Bytes/s> ");
- fprintf(stderr, "-L<Net Latency (ms)> ");
- fprintf(stderr, "[filename]\n\n");
- exit(1);
- }
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- char in_string[MAXSTRINGSIZE];
- char *str_ptr;
- int i;
- char filename[FILENAMESIZE];
- FILE *fp=stdin; /* File pointer to the input file */
- char perffile[FILENAMESIZE];
- FILE *pp;
-
- /*
- * Process the command line arguments
- */
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-') { /* Argument is a flag */
- switch(argv[i][1]) {
- case 'b':
- if (strlen(&argv[i][1]) == 1)
- MAXBUCKETS_SIZE = 4096;
- else MAXBUCKETS_SIZE = atoi(&argv[i][2]);
- break;
- case 'd': /* Set the debug level */
- if (strlen(&argv[i][1]) == 1)
- debuglevel = 1;
- else debuglevel = atoi(&argv[i][2]);
- break;
- case 'p':
- strcpy(perffile, &argv[i][2]);
- if ((pp = fopen(perffile,"r")) == NULL)
- fprintf(stderr,"Error: Can't open initialization file:%s\n"
- ,perffile);
- else {
- parse_parameters(pp);
- init_profile();
- profileflag = TRUE; /* Generate profile */
- }
- break;
- case 's': /* Trap signals ?*/
- if (strlen(&argv[i][1]) == 1)
- trapsignal = TRUE;
- else {
- int flag = atoi(&argv[i][2]);
- if (flag == 0) trapsignal = FALSE;
- else trapsignal = TRUE;
- }
- break;
- case 'v': /* Set the verbosity level */
- if (strlen(&argv[i][1]) == 1)
- verboselevel = 1;
- else verboselevel = atoi(&argv[i][2]);
- break;
- case 'S': /* Set the network speed */
- if (strlen(&argv[i][1]) >= 1)
- set_net_speed ((double) atof(&argv[i][2]) );
- break;
- case 'L': /* Set the network latency */
- if (strlen(&argv[i][1]) >= 1)
- set_net_latency((double) atof(&argv[i][2]) );
- break;
- default:
- Usage(argv[0], argv[i]);
- break;
- }
- }
- else { /* Assume that argument is a filename */
- strcpy(filename, argv[i]);
- if (fp == stdin) { /* Has fp been initialized already ?*/
- if ((fp = fopen(filename,"r")) == NULL) {
- fprintf(stderr,"Error: Can't open input file: %s\n",filename);
- exit(1);
- }
- }
- else Usage(argv[0], filename);
- }
- }
-
- {
- char hostname[128];
- struct timeval tp;
- struct timezone tzp;
-
- gethostname (hostname, 128);
- printf("\"%s\", version %s running on %s.\n",
- argv[0], xprof_version, hostname);
- gettimeofday(&tp, &tzp);
- printf("Date: %s\n", ctime (&tp.tv_sec));
- }
- if (fp == stdin) printf("** Input accepted from stdin **\n");
-
- /*
- * Set up the signal handlers.
- */
- if (trapsignal == TRUE) {
- signal(SIGHUP, onhangup);
- signal(SIGINT, onintr);
- signal(SIGQUIT, onquit);
- signal(SIGFPE, onfpe);
- signal(SIGBUS, onbus);
- signal(SIGSEGV, onsegv);
- signal(SIGXCPU, onxcpu);
- }
-
- /* Main string processing loop */
-
- while ( fgets(in_string, MAXSTRINGSIZE, fp) != NULL) {
- _LINE_NUM++;
- if (strstr(in_string,"Client ") != NULL) {
- if (debuglevel >= 1)
- printf("%s",in_string);
- process_client(in_string, &globalstats);
- }
- else if ((str_ptr = strstr(in_string,"REQUEST")) != NULL) {
- if (debuglevel >= 1)
- printf("%s",in_string);
- process_request(fp, str_ptr, &globalstats);
- }
- else if (strstr(in_string,"<-- X11 Server") != NULL) {
- if (debuglevel >= 1)
- printf("%s",in_string);
- process_server(in_string, &globalstats);
- }
- else if ((str_ptr = strstr(in_string,"REPLY")) != NULL) {
- if (debuglevel >= 1)
- printf("%s",in_string);
- process_reply(fp, str_ptr, &globalstats);
- }
- else if ((str_ptr = strstr(in_string,"EVENT")) != NULL) {
- if (debuglevel >= 1)
- printf("%s",in_string);
- process_event(fp, str_ptr, &globalstats);
- }
- else if ((str_ptr = strstr(in_string,"ERROR")) != NULL) {
- if (debuglevel >= 1)
- printf("%s",in_string);
- process_error(fp, str_ptr, &globalstats);
- }
- }
-
- /* Print out the statistics collected before exiting */
- print_stats(stdout);
- return(0);
- }
-
- /* Process the line corresponding to a message from the client
- * The format of the line is:
- * <timestamp> Client [Client number] --> <Num_bytes> bytes
- *
- * The Client number field is optional
- */
- process_client(string, gstats)
- char *string;
- GlobalStats *gstats;
- {
- float time; /* The time stamp is in the form xx.yy seconds*/
- char junk1[80],junk2[80],junk3[80],junk4[80];
- int client_num; /* This is ignored in the current program */
- unsigned num_bytes=0;
- int i;
-
- i=sscanf(string,"%f %s %s %d %s %d %s", &time, junk1, junk2,
- &client_num, junk3, &num_bytes, junk4);
- if (i != 7) {
- i=sscanf(string,"%f %s %s %s %d %s", &time, junk1, junk2,
- junk3, &num_bytes, junk4);
- if (i !=6) return ;
- }
- /*
- * Now update the global structures for the client
- */
- gstats->last_time = gstats->current_time;
- gstats->current_time = (long) (time * 1000);
- gstats->client_bytes += num_bytes;
- return;
- }
-
- /* Process the line corresponding to a message from the server
- * The format of the line is:
- *
- * <timestamp> <Num_bytes> bytes <-- X11 Server
- *
- */
-
- process_server(string, gstats)
- char *string;
- GlobalStats *gstats;
- {
- float time; /* The time stamp is in the form xx.yy seconds*/
- char junk1[80], junk2[80], junk3[80], junk4[80];
- unsigned num_bytes=0;
- int i;
-
- i = sscanf(string,"%f %s %d %s %s %s", &time,junk1,&num_bytes,
- junk2, junk3, junk4);
- if (i < 6) return;
- /*
- * Now update the global structures for the server
- */
- gstats->last_time = gstats->current_time;
- gstats->current_time = (long) (time * 1000);
- gstats->server_bytes += num_bytes;
- return;
- }
-
- /*
- * print_stats(): Final printout function.
- * It consults the global variable "globalstats" It is not passed any
- * arguments because it may be called by the interrupt service routine.
- */
- print_stats(fp)
- FILE *fp;
- {
- fprintf(fp,"Final line number: %d\n",_LINE_NUM);
- fprintf(fp,"Final time stamp : %.2f Seconds\n",
- (float) globalstats.current_time / 1000.0);
- fprintf(fp,"Messages transferred (In Bytes):\n");
- fprintf(fp," Client Server Requests Replies Events Errors");
- fprintf(fp,"\n%10lu %10lu %10lu %10lu %10lu %10lu\n",
- globalstats.client_bytes, globalstats.server_bytes,
- globalstats.request_bytes, globalstats.reply_bytes,
- globalstats.event_bytes, globalstats.error_bytes);
-
- print_request_stats(fp);
- print_reply_stats(fp);
- print_event_stats(fp);
- print_error_stats(fp);
-
- if (profileflag) print_profile_stats(fp);
- }
-
- /*
- * Print out the statistics of a distribution consisting of maxbuckets buckets
- */
- process_stats(fp, min, max, distbn, grain, maxbuckets, statstype)
- FILE *fp;
- long min;
- long max;
- long distbn[];
- Grain grain;
- long maxbuckets;
- StatsType statstype;
- {
- long number=0; /* Total number of data points. This may be different
- from the number of corresponding messages.*/
- double mean=0.0, variance=0.0, std_dev=0.0;
- long median=0;
- long mode=0;
- long mode_freq=0;
- long n=0;
- double sum=0.0, sum_sq=0.0;
- double tmp;
- int i;
- long datapoint;
-
- /* Collect the total number of data points */
- for (i = 0; i < maxbuckets; i++)
- number += distbn[i];
-
- /* Collect the sums, sum of squares, mode, and median */
- for (i = 0; i < maxbuckets; i++) {
- if (statstype == LOG2) datapoint = (long) myexp2(i);
- else datapoint = i;
- n += distbn[i];
- tmp = (double) distbn[i] * datapoint * (double) grain;
- sum += (double) tmp;
- sum_sq+= (double) tmp * datapoint * (double) grain;
- if (distbn[i] > mode_freq) {
- mode = datapoint;
- mode_freq = distbn[i];
- }
- if (n <= (number / 2))
- median = datapoint;
- }
- if (number > 0) {
- mean = (double) sum / (double) number;
- variance = (double) (sum_sq / (double) number) - (mean * mean);
- std_dev = (double) sqrt(variance);
- }
-
- fprintf(fp,"%-15s ","");
- fprintf(fp,"%6s %15s %7s %7s %10s %10s\n", "Number", "Range ",
- "Mode", "Median", "Mean", "Std. Dev.");
- fprintf(fp,"%-15s ", "(All points)");
- fprintf(fp,"%6ld %7ld-%-7ld %7ld %7ld %10.2f %10.2f\n",
- number, min *(long) grain, max *(long) grain, mode * (long) grain,
- median * (long) grain, mean, std_dev);
- /*
- * Now print out the statistics for all cases except zero interarrival time
- * The same sum and sum_sq can be recycled, since it has not accumalated the
- * zero case anyway !!
- */
- mean = variance = std_dev = 0.0;
- n = median = mode = mode_freq = 0;
- min = max;
-
- /* Collect the sums and the sum of squares */
- number -= distbn[0];
- if (number > 0) {
- for (i = 1; i < maxbuckets; i++) {
- if (statstype == LOG2) datapoint = (long) myexp2(i);
- else datapoint = i;
- if (distbn[i] > 0) {
- n += distbn[i];
- if (min > datapoint) min = datapoint;
- }
-
- if (distbn[i] > mode_freq) {
- mode = datapoint;
- mode_freq = distbn[i];
- }
- if (n <= (number / 2))
- median = datapoint;
- }
- mean = (double) sum / (double) number;
- variance = (double) (sum_sq / (double) number) - (mean * mean);
- std_dev = (double) sqrt(variance);
-
- fprintf(fp,"%-15s ", "(Zeros removed)");
- fprintf(fp,"%6ld %7ld-%-7ld %7ld %7ld %10.2f %10.2f\n",
- number, min * (long) grain, max * (long) grain,
- mode * (long) grain, median * (long) grain, mean, std_dev);
- }
- }
-
- /* t_search
- Look for existence of token string in the initial position of another string
- Returns 1 on success, 0 otherwise.
- */
- int t_search(string, token)
- char *string, *token;
- {
- while (*token) {
- if ((*token != *string) || !(*string))
- return (0); /* Return if there is a mismatch or we run out of
- characters in the string */
- token ++; string ++;
- }
- return (1); /* Succesful return */
- }
-
- /*
- * Signal handler routines are defined here
- * In order to force a printout AND continue execution execute the command
- * kill -1 <process-number> from the shell.
- */
- #define ONSIGNAL(function, signame, terminate) void function() {\
- sighandler(signame, terminate); \
- }
-
- ONSIGNAL(onhangup, "Hangup", FALSE);
- ONSIGNAL(onintr, "Interrupt", TRUE);
- ONSIGNAL(onquit, "Quit", TRUE);
- ONSIGNAL(onfpe, "Floating point exception", TRUE);
- ONSIGNAL(onbus, "Bus Error", TRUE);
- ONSIGNAL(onsegv, "Segmentation violation", TRUE);
- ONSIGNAL(onxcpu, "Cpu limit exceeded", TRUE);
-
- sighandler(signame, terminate)
- char *signame;
- Boolean terminate;
- {
- fflush(stdout);
- fprintf(stderr, "\t=== %s signal trapped ===\n", signame);
- fflush(stderr);
- print_stats(stderr);
- fflush(stderr);
- fflush(stdout);
- if (terminate == TRUE)
- abort();
- }
-